/*
 * @Author: linxun 
 * @Date: 2021-03-06 14:30:33 
 * @Last Modified by: linxun
 * @Last Modified time: 2021-07-29 11:29:09
 * @Description: 数据集图片管理
 */

import React, { useEffect, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { PageHeader, Card, Row, Col, Button, Alert, message, Modal, Input, Checkbox } from 'antd';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { useIntl, history, connect } from 'umi';
import {
  fetchImgs,
  fetchImgsByDataSetId,
  addImagesByUpload,
  addImagesByPath,
  addImagesByCondition,
  addImagesByKeys,
  delImgs,
  delImgsByImgIds,
  createTask,
  getTaskIdByDataSetId,
  downloadImages,
} from './service';
import AddImageModal from './components/AddImage';
import ImageViewer from './components/ImageViewer';
import SamplesImages from './components/SamplesImages';
import SamplesSearch from './components/SamplesSearch';
import moment from 'moment';
import { addonBeforePath } from './components/SecondStep';
import { ANNOTATIONS_BACKEND } from '@/utils/const';

import styles from './Samples.less';

const { Search } = Input;

const PAGEPARAMS = {
  pageNum: 1,
  pageSize: 12,
};

const Samples = props => {
  const { formatMessage } = useIntl();
  const dataSetId = ~~props.match.params.id;
  const { dataSet: { createSourceType }, dispatch, location: { pathname } } = props;
  const isPublic = pathname?.includes('public');
  const option = props.location.state?.option || props.location.query?.option;
  const annotType = props.location.state?.annotType || props.location.query.annotType;
  const [imageData, setImageData] = useState([]);
  const [curImageIndex, setCurImageIndex] = useState(-1);
  const [pagination, setPagination] = useState({ current: 1, pageSize: PAGEPARAMS.pageSize });
  const [loading, setLoading] = useState({
    getData: false,
    addImage: false,
    download: false,
  });
  const [visible, setVisible] = useState({
    addImage: false,
    image: false,
  });
  const [checkedKeys, setCheckedKeys] = useState([]);
  const [checkedAnnotIds, setCheckedAnnotIds] = useState([]);
  const [searchValues, setSearchValues] = useState({});
  const [canAnnot, setCanAnnot] = useState(false);
  const [taskId, setTaskId] = useState(undefined);

  const getTaskId = async () => {
    const res = await getTaskIdByDataSetId({ id: dataSetId });
    if (res && res.code === 0) {
      const { imageTaskId } = res.data;
      setTaskId(imageTaskId || '');
    } else {
      setTaskId('');
    }
  };

  const getImgs = async params => {
    setLoading({ ...loading, getData: true });
    const newParams = {
      ...pagination,
      pageNum: pagination.current,
      total: undefined,
      current: undefined,
      ...searchValues,
      ...params,
    }
    const res = taskId ? await fetchImgs({
      id: taskId,
      ...newParams,
    }) : await fetchImgsByDataSetId({
      id: dataSetId,
      ...newParams,
    });
    setLoading({ ...loading, getData: false });
    if (res.code === 0) {
      const { items, total } = res.data;
      setImageData(taskId ? items || [] : items.map(i => ({ id: i.id, image: i })));
      setPagination({
        ...pagination,
        current: newParams?.pageNum || pagination.current,
        pageSize: newParams?.pageSize || pagination.pageSize,
        total,
      });
    }
  };

  useEffect(() => {
    if (!createSourceType.length) {
      dispatch({ type: 'dataSet/getCreateSourceType' });
    }
    getTaskId();
  }, []);

  useEffect(() => {
    if (taskId !== undefined) {
      getImgs();
    }
  }, [taskId, searchValues]);

  const onPageChange = (current, pageSize) => {
    // setCheckedKeys([]);
    getImgs({
      pageNum: current,
      pageSize,
    });
  };

  const onAddImage = async (values, rowDataRef) => {
    setLoading({ ...loading, addImage: true });
    const { sourceType, storagePath, fileList, withAnnotFile } = values;
    if (sourceType === 'make_from_files') {
      // 原始数据导入
      const { selectWay } = values;
      const { searchParams, selectKeys } = rowDataRef.current;
      let params = {
        cvDatasetId: dataSetId,
        sourceType,
      };
      if (selectWay === 1) {
        // if (JSON.stringify(searchParams) === '{}') {
        //   message.warning('请至少输入一个筛选条件！');
        //   return;
        // }
        params = {
          cvDatasetId: dataSetId,
          sourceType,
          ...searchParams,
        };
      } else {
        if (!selectKeys || !selectKeys.length) {
          message.warning('请至少选择一条数据！');
          return;
        }
        params.fileList = selectKeys;
      }
      const res = selectWay === 1 ? await addImagesByCondition(params) : await addImagesByKeys(params);
      setLoading({ ...loading, addImage: false });
      if (res && res.code === 0) {
        message.success('添加成功');
        setVisible({ ...visible, addImage: false });
        getImgs();
        // } else if (res.code === 220030124) {
        //   message.error('cv数据集未标注，不可添加图片');
      }
    } else {
      // 网页上传 平台导入
      const uploadPath = sourceType === 'upload_from_page' ? fileList[0]?.response?.data?.storagePath : undefined;
      const params = {
        id: dataSetId,
        sourceType,
        withAnnotFile,
        dirPath: uploadPath || addonBeforePath + storagePath,
        fileName: sourceType === 'upload_from_page' ? fileList[0]?.name : undefined,
      }
      const res = sourceType === 'upload_from_page'
        ? await addImagesByUpload(params)
        : await addImagesByPath(params);
      setLoading({ ...loading, addImage: false });
      if (res && res.code === 0) {
        message.success('添加成功');
        setVisible({ ...visible, addImage: false });
        getImgs();
        // } else if (res.code === 220030124) {
        //   message.error('cv数据集未标注，不可添加图片');
      }
    }
  };

  const onCheckboxChange = (e, record) => {
    const { checked } = e.target;
    const curId = taskId ? record.imageId : record.id;
    const set = new Set(checkedKeys);
    checked ? set.add(curId) : set.delete(curId);
    setCheckedKeys(Array.from(set));
    if (taskId) {
      // 存储annotId
      const curAnnotId = record.id;
      const annotSet = new Set(checkedAnnotIds);
      checked ? annotSet.add(curAnnotId) : annotSet.delete(curAnnotId);
      setCheckedAnnotIds(Array.from(annotSet));
    }
  };

  const onCurPageChecked = e => {
    const { checked } = e.target;
    const set = new Set(checkedKeys.concat(imageData.map(i => taskId ? i.imageId : i.id)));
    imageData.forEach(i => {
      const curId = taskId ? i.imageId : i.id;
      checked ? set.add(curId) : set.delete(curId);
    });
    setCheckedKeys(Array.from(set));
    if (taskId) {
      // 存储annotId
      const annotSet = new Set(checkedAnnotIds);
      imageData.forEach(i => {
        const curAnnotId = i.id;
        checked ? annotSet.add(curAnnotId) : annotSet.delete(curAnnotId);
      });
      setCheckedAnnotIds(Array.from(annotSet));
    }
  };

  useEffect(() => {
    if (!checkedKeys.length) {
      setCheckedAnnotIds([]);
    }
  }, [checkedKeys]);

  const checkCurPageChecked = () => {
    if (!imageData.length) return false;
    if (!checkedKeys.length) return false;
    return imageData.every(i => checkedKeys.includes(taskId ? i.imageId : i.id))
  };

  const batchDelete = () => {
    Modal.confirm({
      title: '确定删除所选项吗？',
      icon: <ExclamationCircleOutlined />,
      onOk: async () => {
        const hide = message.loading('正在删除...');
        const res = taskId ? await delImgs({
          annotIds: checkedAnnotIds,
        }) : await delImgsByImgIds({
          id: dataSetId,
          imageIds: checkedKeys,
        });
        hide();
        if (res && res.code === 0) {
          message.success('删除成功');
          setCheckedKeys([]);
          getImgs();
        }
      },
      okType: 'danger',
    });
  };

  const onImageClick = record => {
    setVisible({ ...visible, image: true });
    const index = imageData.findIndex(i => i.id === record.id);
    setCurImageIndex(index);
  };

  const onTabsChange = (activeKey) => {
    setCheckedKeys([]);
    setCanAnnot(activeKey === 'canlabeled');
    setPagination({
      ...pagination,
      current: 1,
    });
    setSearchValues({
      ...searchValues,
      status: activeKey || undefined,
    });
  };

  const onSearch = (value, key) => {
    setCheckedKeys([]);
    const params = {};
    const timeKeys = ['createdTime', 'annotTime'];
    if (key === 'createdTime') {
      params.createStart = value && value[0] ? moment(value[0]).format('x') : undefined;
      params.createStop = value && value[1] ? moment(value[1]).format('x') : undefined;
    } else if (key === 'annotTime') {
      params.annotStart = value && value[0] ? moment(value[0]).format('x') : undefined;
      params.annotStop = value && value[1] ? moment(value[1]).format('x') : undefined;
    } else {
      params[key] = value || undefined;
    }
    setPagination({
      ...pagination,
      current: 1,
    });
    setSearchValues({
      ...searchValues,
      ...params,
    });
  };

  const batchDownload = async () => {
    const hide = message.loading('正在获取下载链接...', 0);
    setLoading({ ...loading, download: true });
    const res = await downloadImages({
      cvDatasetId: dataSetId,
      imageIds: checkedKeys,
    });
    hide();
    setLoading({ ...loading, download: false });
    if (res && res.code === 0) {
      Modal.confirm({
        title: '温馨提示',
        content: '下载准备完成，请保存',
        icon: <EyeOutlined />,
        maskClosable: false,
        onOk: () => {
          window.open(res.data?.downloadLink);
          return Promise.reject();
        },
        okText: '保存',
        cancelText: '关闭',
      });
    }
  };

  const toAnnot = async () => {
    const hide = message.loading('正在加载...');
    const res = await createTask({
      imageTaskId: taskId,
      annotIds: checkedAnnotIds,
    });
    hide();
    if (res && res.code === 0) {
      message.success('创建成功');
      const { imageTaskId } = res.data;
      const hostName = `${window.location.origin}${ANNOTATIONS_BACKEND}`;
      window.open(`${hostName}/tasks/${imageTaskId || taskId}?annotType=${annotType}`);
      setCheckedKeys([]);
      getImgs();
    }
  };

  return (
    <PageHeaderWrapper title={false}>
      <PageHeader
        ghost={false}
        // onBack={history.goBack}
        onBack={() => history.push(isPublic ? '/public' : '/QIP/dataManage/dataSet')}
        title={formatMessage({ id: 'menu.dataManage.samples' })}
      ></PageHeader>
      <Card className={styles.card}>
        <Row className={styles.options}>
          <Col span={24}>
            {option !== '1' && (
              <Button
                type='primary'
                className={styles.btn}
                onClick={() => setVisible({ ...visible, addImage: true })}
              >添加图片</Button>
            )}
            <Button
              type='primary'
              disabled={!checkedKeys.length || loading.download}
              className={styles.btn}
              onClick={batchDownload}
            >批量下载</Button>
            {option === '1' && (
              <Button
                type='primary'
                danger
                disabled={!checkedKeys.length || loading.download}
                className={styles.btn}
                onClick={batchDelete}
              >{formatMessage({ id: 'dataSet.batchDel' })}</Button>
            )}
            {canAnnot &&
              <Button
                type='primary'
                disabled={!checkedKeys.length}
                className={styles.btn}
                onClick={toAnnot}
              >创建标注任务</Button>
            }
            <Checkbox
              checked={checkCurPageChecked()}
              onChange={onCurPageChecked}
              className={styles.checkAll}
            >本页全选</Checkbox>
          </Col>
        </Row>
        <SamplesSearch
          onTabsChange={onTabsChange}
          onSearch={onSearch}
          taskId={taskId}
        />
        {checkedKeys.length > 0 &&
          <Alert
            message={formatMessage({ id: 'dataSet.table.selected' }, { count: checkedKeys.length })}
            showIcon
            className={styles.alert}
            closeText={(
              <a onClick={() => setCheckedKeys([])}>
                {formatMessage({ id: 'dataSet.table.cancelSelected' })}
              </a>
            )}
          />
        }
        <SamplesImages
          imgs={imageData}
          checkedKeys={checkedKeys}
          onCheckboxChange={onCheckboxChange}
          onImageClick={onImageClick}
          pagination={pagination}
          onPageChange={onPageChange}
          loading={loading.getData}
          taskId={taskId}
        />
      </Card>
      <AddImageModal
        visible={visible.addImage}
        cancel={() => setVisible({ ...visible, addImage: false })}
        loading={loading.addImage}
        onOk={onAddImage}
        createSourceType={createSourceType}
        hideWithAnnotFile
      />
      <ImageViewer
        visible={visible.image}
        cancel={() => setVisible({ ...visible, image: false })}
        imgs={imageData}
        initIndex={curImageIndex}
        annotType={annotType}
        option={option}
        taskId={taskId}
      />
    </PageHeaderWrapper>
  )
}

export default connect(({ oldDataSet }) => ({
  dataSet: oldDataSet,
}))(Samples);